package com.game.service.game.turntable;

import com.game.service.app.Deduction;
import com.game.service.app.FeeOrderReturn;
import com.game.service.app.Utils;
import com.game.service.app.get_score.UserLoginInfo;
import com.game.service.beans.GameConfig;
import com.game.service.beans.UserInfo;
import com.game.service.db.UserScoreDaoImpl;
import com.game.service.socket.FileUtils;
import com.game.service.socket.SocketServer;
import com.game.service.game.turntable.config.Prize;
import com.game.service.game.turntable.config.PrizeDailyTask;
import com.game.service.game.turntable.config.PrizeLuckyStore;
import com.game.service.game.turntable.config.TablePrizeItemList;
import com.game.service.game.turntable.control.LifeSaving;
import com.game.service.game.turntable.control.LifeSavingRequirement;
import com.game.service.windows.LogWindows;
import com.google.gson.Gson;

import java.util.ArrayList;

import static com.game.service.app.Utils.LogDate;
import static com.game.service.app.Utils.random;
import static com.game.service.define.RoomConfig.*;
import static com.game.service.define.RoomConfig.ORDER_PRIZE;

public class TurntableAddConfig {

    /***
     * 一类房间,该房间6~30倍中奖机率(翻倍8%),中奖概率50%
     */
    public static final float[][] turntableConfig1 = {
            //编号,倍率,概率(10000份),转盘位置
            //大奖
            {0, 150, 1, 15}, {1, 80, 2, 1}, {2, 50, 3, 9}, {3, 30, 50, 13}, {4, 20, 80, 5}, {5, 10, 160, 3}, {6, 8, 200, 7}, {7, 6, 300, 11},
            //小奖
            {8, 2, 100, 14}, {9, 1.8f, 100, 10}, {10, 1.5f, 100, 8}, {11, 1.2f, 100, 4}, {12, 0.6f, 100, 6}, {13, 0.4f, 100, 2}, {14, 0.2f, 100, 12}, {15, 0, 0, 0}};


    /***
     * 二类房间,该房间6~30倍中奖机率(4%),中奖概率80%
     */
    public static final float[][] turntableConfig2 = {
            //编号,倍率,概率(10000份),转盘位置
            //大奖
            {0, 150, 1, 15}, {1, 80, 2, 1}, {2, 50, 3, 9}, {3, 30, 20, 13}, {4, 20, 40, 5}, {5, 10, 80, 3}, {6, 8, 100, 7}, {7, 6, 150, 11},
            //小奖
            {8, 2, 400, 14}, {9, 1.8f, 450, 10}, {10, 1.5f, 520, 8}, {11, 1.2f, 650, 4}, {12, 0.6f, 1000, 6}, {13, 0.4f, 1500, 2}, {14, 0.2f, 3000, 12}, {15, 0, 0, 0}};

    /**
     * 动态押注分数数组,配合(押注倍率)使用
     */
    public static final int[] betArray = {10, 50, 100, 500, 1000, 2000};
    /**
     * 押注倍率 1,10,50,100等
     */
    public static final int roomRatio = 1;

    /**
     * 动态押注抽杀数组,配合(基础抽杀)使用,
     * 全程生效(保护期间除外,基础抽杀 + 动态抽杀)
     */
    public static final float[] betArrayKill = {0, 0, 0, 1, 2, 4};//杀大赔小

    /**
     * 动态新手保护数组,配合(保护次数)使用,
     * 新手保护期间时生效(基础保护 + 动态保护),
     */
    //  public static final float[] betArrayProtect = {20, 15, 8, 4, 2, 1, -2, -4, -8, -10};//保护与活动不要一起，需要控制返奖率
    public static final float[] betArrayProtect = {0, 0, 0, 0, 0, 0};
    /**
     * 幸运用户百分比(0~100)
     */
    public static final int lucky = 100;//
    /**
     * 基础抽杀机率百分比(0~10),不得为负数,否则有严重后果
     */
    public static final float kill = 2;//
    /**
     * 基础保护机率百分比(0~10),不得超过10,否则会有严重后果
     */
    public static final float protect = 0;//
    /**
     * 新手保护次数(0~200)
     */
    public static final int protectCounts = 150;//新手保护次数

    /**
     * 开设房间(1,开房间一  2, 开房间二   0, 表示全开)
     */
    public static final int openTable = 1;//


    public static long mDiamondMax = 0;
    public static long mBetIndex = 0;

    /***
     * 游戏房间配置信息，优先加载数据库配置，缺少则加载本地默认配置
     */
    private static TurntableConfig mTurntableConfig = null;

    private static boolean isDebug = false;

    public static synchronized TurntableConfig getConfig() {
        if (mTurntableConfig == null) {
            initGameConfig();
        }
        return mTurntableConfig;
    }

    public static void initGameConfig() {
        GameConfig gameConfig = UserScoreDaoImpl.getInstance().getGameConfig(GAME_ID);
        String dbConfig = null;
        if (gameConfig != null) {
            dbConfig = gameConfig.getConfig();
        }
        if (dbConfig != null && dbConfig.length() > 2) {
            mTurntableConfig = new Gson().fromJson(dbConfig, TurntableConfig.class);
            String log = String.format("加载数据库-游戏配置%s", dbConfig);
            LogWindows.getLogWindows().printToTextArea(log, TurntableAddConfig.class);
            printPayoutRate("房间1返奖率", mTurntableConfig.getTablePrizeItemList().getTable1prizeItems());
            printPayoutRate("房间2返奖率", mTurntableConfig.getTablePrizeItemList().getTable2prizeItems());
            FileUtils.writeTxtToFile(log, LogDate(), LOG_NAME_ROOM);
        }
        if (mTurntableConfig == null) {//如果数据库里也没有则使用程序初始设置
            mTurntableConfig = new TurntableConfig();
            TablePrizeItemList prizeItemList = new TablePrizeItemList();
            int zeroWeight = 10000;
            //初始化桌子1的配置
            for (int i = 0; i < 16; i++) {
                PrizeItem item = new PrizeItem();
                item.setId((int) turntableConfig1[i][0]);
                item.setRate(turntableConfig1[i][1]);
                item.setWeight((int) turntableConfig1[i][2]);
                item.setPos((int) turntableConfig1[i][3]);
                //剩余的都给0
                zeroWeight -= (int) turntableConfig1[i][2];
                if (i == 15) {
                    item.setWeight(zeroWeight);
                }
                prizeItemList.getTable1prizeItems().add(item);
            }
            //初始化桌子2的配置
            zeroWeight = 10000;
            for (int i = 0; i < 16; i++) {
                PrizeItem item = new PrizeItem();
                item.setId((int) turntableConfig2[i][0]);
                item.setRate(turntableConfig2[i][1]);
                item.setWeight((int) turntableConfig2[i][2]);
                item.setPos((int) turntableConfig2[i][3]);
                //剩余的都给0
                zeroWeight -= (int) turntableConfig2[i][2];
                if (i == 15) {
                    item.setWeight(zeroWeight);
                }
                prizeItemList.getTable2prizeItems().add(item);
            }
            mTurntableConfig.setTablePrizeItemList(prizeItemList);
            mTurntableConfig.setPrizeDailyTask(new PrizeDailyTask().initPrizeDaily(betArray)); //初始化-每日活动任务内容
            mTurntableConfig.setPrizeLuckyStore(new PrizeLuckyStore()); //初始化-幸运积分商店
            mTurntableConfig.setLifeSavingRequirement(new LifeSavingRequirement().initRequirement());
            mTurntableConfig.setLucky(lucky);//设置幸运用户百分比
            mTurntableConfig.setKill(kill);//设置抽杀机率
            mTurntableConfig.setBetArray(betArray);//设置动态押注
            mTurntableConfig.setRoomRatio(roomRatio);//设置房间
            mTurntableConfig.setProtect(protect);//设置新手保护概率
            mTurntableConfig.setProtectCounts(protectCounts);//设置新手保护次数
            mTurntableConfig.setBetArrayKill(betArrayKill);//动态押注,带抽杀机率
            mTurntableConfig.setBetArrayProtect(betArrayProtect);//动态押注,带保护机率
            mTurntableConfig.setOpenTable(openTable);//设置桌子

            String location = new Gson().toJson(mTurntableConfig);//添加到数据库使用
            String log = String.format("加载本地-游戏配置%s", location);
            LogWindows.getLogWindows().printToTextArea(log, TurntableAddConfig.class);
            printPayoutRate("房间1返奖率", mTurntableConfig.getTablePrizeItemList().getTable1prizeItems());
            printPayoutRate("房间2返奖率", mTurntableConfig.getTablePrizeItemList().getTable2prizeItems());
        }
    }


    public static void initGameConfigNet(TurntableConfig mTurntableConfigNet) {
        mTurntableConfig = mTurntableConfigNet;
        FileUtils.writeTxtToFile("加载总服务器-游戏配置" + mTurntableConfig, LogDate(), LOG_NAME_ROOM);
    }

    /***
     * @return 返回中奖项
     */
    private static PrizeItem model(ArrayList<PrizeItem> prizeItems) {
        int random = random(1, 10000);
        for (PrizeItem prizeItem : prizeItems) {
            random -= prizeItem.getWeight();
            if (random <= 0) {
                return prizeItem;
            }
        }
        return null;
    }

    /***
     *
     * @param orderid 订单id
     * @param feeOrderReturn 原始分数
     * @param userBet 投注信息
     * @return 中奖结果
     */
    public static GameResult onTurntableGameResult(String orderid, FeeOrderReturn feeOrderReturn, UserBet userBet) {
        ArrayList<PrizeItem> prizeItems = null;

        if (userBet.getTableType() == 1) {//房间1 配置
            prizeItems = getConfig().getTablePrizeItemList().getTable1prizeItems();
        }
        if (userBet.getTableType() == 2) {//房间2 配置
            prizeItems = getConfig().getTablePrizeItemList().getTable2prizeItems();
        }
        if (prizeItems == null) {//默认为第一种,防止客户端篡改房间
            prizeItems = getConfig().getTablePrizeItemList().getTable1prizeItems();
        }

        PrizeItem item;
        final int betIndex = getBetIndex(userBet.getBet());//校正投注代号，默认为第一个.
        final int betNumber = getBetNumber(betIndex);//获取实际的押注,防止客户端篡改押注
        //玩家游玩次数信息
        UserInfo userInfo = SocketServer.getKernel().getUserMap().get(userBet.getUid());
        boolean isNewPlayer = userInfo.getPlayCounts() < getConfig().getProtectCounts();
        boolean isLuckyPlayer = userInfo.getLuckyValue() > 100 - getConfig().getLucky();

        if (isNewPlayer && isLuckyPlayer) {//如果是新手玩家并且是幸运用户,则使用新手玩家的保护机制。

            int randomProtect = random(1, 100);
            float protect = getConfig().getProtect();//基础保护机率
            float betProtect = getBetArrayProtect(betIndex);//动态保护机率

            if (randomProtect <= protect + betProtect) {//最终保护机率=基础保护机率+动态保护
                int randomPrize = random(5, 7);//随机给 10倍,8倍,6倍
                item = prizeItems.get(randomPrize);
                item.setItemStatus(2);
            } else {
                item = getPrizeItem(userInfo, betNumber, prizeItems);
            }

        } else {//过了新手保护期,优先判断抽杀

            int randomKill = random(1, 100);
            float kill = getConfig().getKill();
            float betKill = getBetArrayKill(betIndex);
            if (randomKill <= kill + betKill) {//一旦抽杀,则直接开不中奖
                item = prizeItems.get(15);
                item.setItemStatus(1);
            } else {
                item = getPrizeItem(userInfo, betNumber, prizeItems);
            }

        }

        assert item != null;

        userInfo.setPlayCountsAdd();//记录玩家游戏次数
        userInfo.getPrize().add(betIndex, item);//新增玩家游玩信息记录表prize
        long  score = feeOrderReturn.getScore();
        GameResult gameResult = new GameResult();
        gameResult.orderid = orderid;
        gameResult.score = score;
        gameResult.item = item.getPos();
        gameResult.betid = betIndex;//新增记录下注id 对应betArray[]
        gameResult.prizeid = item.getId();//返奖id 对应tableItems[]
        gameResult.itemStatus = item.getItemStatus();//生成状态
        gameResult.ratio = "x" + item.getRate();
        gameResult.fee = betNumber;
        gameResult.prize = (int) (betNumber * item.getRate());
        gameResult.deduction=feeOrderReturn.getDeduction();//本次玩家扣除内容
        userInfo.setScore(score + gameResult.prize);//记录玩家当前分数

        return gameResult;


    }

    /*** 执行拯救
     * 先判断是否满足拯救条件
     *
     * @param userInfo 用户信息
     * @param betNumber 用当前押注
     * @param prizeItems //开奖配置
     * @return 奖项
     */
    private static PrizeItem getPrizeItem(UserInfo userInfo, int betNumber, ArrayList<PrizeItem> prizeItems) {
        PrizeItem item;
        LifeSaving lifeSaving = new LifeSaving(userInfo, betNumber);
        final long openPrize = lifeSaving.checkingLifeSaving();
        if (openPrize != 0) {//满足拯救条件开奖
            item = lifeSaving.createPrizeItem(openPrize);
            item.setItemStatus(3);
        } else {
            item = model(prizeItems);
            assert item != null;
            item.setItemStatus(0);
        }
        return item;
    }

    public static int getBetNumber(int betIndex) {
        return getConfig().getBetArray()[betIndex] * getConfig().getRoomRatio();
    }

    public static float getBetArrayKill(int betIndex) {
        return getConfig().getBetArrayKill()[betIndex];
    }

    public static float getBetArrayProtect(int betIndex) {
        return getConfig().getBetArrayProtect()[betIndex];
    }

    /**
     * 防止客户端篡改数据导致数据异常
     */
    public static int getBetIndex(int betIndex) {
        if (betIndex >= 0 && betIndex < getConfig().getBetArray().length) {
            return betIndex;
        }
        return 0;
    }

    /**
     * 防止客户端篡改数据导致数据异常
     */
    public static int getPrizeDailyIndex(int prizeDailyIndex) {
        if (prizeDailyIndex >= 0 && prizeDailyIndex < getConfig().getPrizeDailyTask().getPrizeDailyList().size()) {
            return prizeDailyIndex;
        }
        return 0;
    }

    public static void printPayoutRate(String desc, ArrayList<PrizeItem> prizeItems) {

        float payoutRate = 0;
        for (PrizeItem prizeItem : prizeItems) {
            payoutRate += (prizeItem.getRate() * prizeItem.getWeight() / 100);
        }
        String log = desc + ":" + String.format("%.2f", payoutRate) + "%";
        LogWindows.getLogWindows().printToTextArea(log, TurntableAddConfig.class);
    }


    private static long tableIdIndex = 100000000;//游戏场次ID

    /***
     *
     * @return  "game_GAME_ID_时间_";
     */
    private static String orderIdHead() {
        tableIdIndex++;
        return "game_" + GAME_ID + "_" + Utils.getDateTableId() + "_";
    }

    public static void testBet() {
        isDebug = true;
        int uid = 10002;
        int playCounts = UserScoreDaoImpl.getInstance().getPlayCounts(GAME_ID, uid);
        UserInfo userInfo = new UserInfo();
        userInfo.setUid(uid);
        userInfo.setMac("token");
        userInfo.setPlayCounts(playCounts);
        userInfo.setLuckyValue(random(1, 100));
        userInfo.setUserLoginInfo(new UserLoginInfo());
        Prize prize = new Prize();
        prize.loadDb(GAME_ID, uid, betArray);
        userInfo.setPrize(prize);
        SocketServer.getKernel().getUserMap().put(uid, userInfo);
        //
        FeeOrderReturn feeOrderReturn= new FeeOrderReturn();
        feeOrderReturn.setCoin(1000);
        feeOrderReturn.setScore(100000);
        feeOrderReturn.setDeduction(new Deduction());

        long mDiamond = 2000000;
        for (int i = 0; i < 1000; i++) {
            int betIndex = random(0, 5);
            mDiamond -= (long) betArray[betIndex] * roomRatio;
            UserBet userBet = new UserBet();
            userBet.setUid(uid);
            userBet.setToken("token");
            userBet.setLiveid(-999);
            userBet.setStream("-9999_-9999");
            userBet.setBet(betIndex);

            String orderIdHead = orderIdHead();
            userBet.setOrderIdFee(orderIdHead + ORDER_FEE + tableIdIndex);
            userBet.setOrderIdPrize(orderIdHead + ORDER_PRIZE + tableIdIndex);
            userBet.setTableType(random(1, 1));

            SocketServer.getKernel().feeOrderSuccess(null, userBet, feeOrderReturn);
//            GameResult gameResult = onTurntableGameResult(userBet.getOrderIdPrize(), mDiamond, userBet);

            //  mDiamond += gameResult.prize;
            //  System.out.println(mDiamond + "");
            if (mDiamond < 0) {
                System.out.println("输完了,第" + i + "把");
                break;
            }
            if (mDiamond > mDiamondMax) {
                mDiamondMax = mDiamond;
                mBetIndex = i;
            }
        }


    }

}
